--
-- Author: zhouzhanglin
-- Date: 2014-10-10 08:48:48
--
local UIPageScrollView=class("UIPageScrollView",ext.Component)
UIPageScrollView.DIRECTION_VERTICAL     = 1
UIPageScrollView.DIRECTION_HORIZONTAL   = 2

function UIPageScrollView:ctor( size,direction,perCount,renderGap)
    UIPageScrollView.super.ctor(self)
    self.direction = direction or UIPageScrollView.DIRECTION_HORIZONTAL

    self:setAnchorPoint(cc.p(0.5,0.5))
    self:setContentSize(size.width,size.height)
    self:setTouchEnabled(true)
    self.lockDrag = false
    self.speed=0.5
    self.renderGap = renderGap or 20

    self._totalPage = 0 
    self._currentPage = 1
    self._endPos = 0

    self._beganPos=cc.p(0,0)
    self._containerPos=cc.p(0,0)
    self._delta=cc.p(0,0)
    self._offsetX = 0
    self._offsetY = 0 
    self._touchIsDown = false 
    self._renderNum = 0 --render的总数量
    self._perCount = perCount or 1 --一页显示几个render

    self._container = display.newNode()
    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        self._clipNode = display.newClippingRegionNode(cc.rect(0,-size.height/2,size.width,size.height))
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        self._clipNode = display.newClippingRegionNode(cc.rect(-size.width/2,-size.height,size.width,size.height))
    end
    self._clipNode:addChild(self._container)
    --设置到最左边和最上边
    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        self._clipNode:setPosition( self:getContentSize().width/2-size.width/2,self:getContentSize().height/2)
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        self._clipNode:setPosition(self:getContentSize().width/2,self:getContentSize().height/2+size.height/2)
    end
    self:addChild(self._clipNode)


    self._enabledUpdate = false
    self:addNodeEventListener(cc.NODE_ENTER_FRAME_EVENT, handler(self, self._onEnterFrame))
    self:addNodeEventListener(cc.NODE_TOUCH_EVENT, handler(self, self._onTouchHandler))
end

function UIPageScrollView:getTotalPage()
    return self._totalPage+1
end

function UIPageScrollView:getCurrentPage()
    return self._currentPage
end
function UIPageScrollView:setClippingEnabled(value)
    self._clipNode:setClippingEnabled(value)
end


function UIPageScrollView:nextPage()
    if self:hasNextPage() then  self._currentPage =self._currentPage +1 end
    local endPos = 0
    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        endPos = -(self._currentPage-1)*self:getContentSize().width
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        endPos = (self._currentPage-1)*self:getContentSize().height
    end
    if self._endPos~=endPos then
        self._endPos = endPos
        if self._onPageChangeFun~=nil then
            self._onPageChangeFun(self._currentPage,self:getTotalPage())
        end
        if not self._enabledUpdate then
            self._enabledUpdate = true
            self:scheduleUpdate()
        end
    end
end

function UIPageScrollView:prevPage()
    if self:hasPrevPage() then  self._currentPage =self._currentPage -1 end
    local endPos = 0
    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        endPos = -(self._currentPage-1)*self:getContentSize().width
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        endPos = (self._currentPage-1)*self:getContentSize().height
    end
    if math.abs(self._endPos- endPos)>1 then
        self._endPos = endPos
        if self._onPageChangeFun~=nil then
            self._onPageChangeFun(self._currentPage,self:getTotalPage())
        end
        if not self._enabledUpdate then
            self._enabledUpdate = true
            self:scheduleUpdate()
        end
    end
end

function UIPageScrollView:_backPage()
    local endPos = 0
    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        endPos = -self._currentPage*self:getContentSize().width
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        endPos = self._currentPage*self:getContentSize().height
    end
    if math.abs(self._endPos- endPos)>1 then
        self._endPos = endPos 
        if self._onPageChangeFun~=nil then
            self._onPageChangeFun(self._currentPage,self:getTotalPage())
        end
        if not self._enabledUpdate then
            self._enabledUpdate = true
            self:scheduleUpdate()
        end
    end
end

function UIPageScrollView:hasNextPage()
    return self._currentPage<self._totalPage+1
end

function UIPageScrollView:hasPrevPage()
    return self._currentPage>1
end



function UIPageScrollView:addItem(render)
    render:setTouchEnabled(true)
    render:setTouchSwallowEnabled(false)

    if self._renderNum>0 and self._renderNum%self._perCount==0 then
        self._totalPage = self._totalPage+1
    end

    if self._renderSize == nil then
        local size = render:getCascadeBoundingBox().size
        self._renderSize = cc.size(size.width,size.height)
    end

    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
        local pageOffset = self:getContentSize().width*self._totalPage+self._renderSize.width/2
        local initOffset = (self:getContentSize().width-self._renderSize.width*self._perCount-self.renderGap*(self._perCount-1) )*0.5 
        local px = pageOffset+initOffset+(self._renderNum%self._perCount)*(self._renderSize.width + self.renderGap) 
        render:setPositionX( px )
    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
        local pageOffset = self:getContentSize().height*self._totalPage+self._renderSize.height/2
        local initOffset = (self:getContentSize().height-self._renderSize.height*self._perCount-self.renderGap*(self._perCount-1) )*0.5 
        local py = -pageOffset-initOffset-(self._renderNum%self._perCount)*(self._renderSize.height + self.renderGap) 
        render:setPositionY( py )
    end

    self._container:addChild(render)
    self._renderNum = self._renderNum +1
    render.__index = self._renderNum
end

function UIPageScrollView:clearPages()
    self._container:removeAllChildren()
    self._container:setPosition(0,0)
end

function UIPageScrollView:scrollToPage(page,animation)
    if page<1 then page=1
    elseif page>self._totalPage then page = self._totalPage end
    self._currentPage=page
    if animation then
        if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
            self._endPos = -(self._currentPage-1)*self:getContentSize().width
        elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
            self._endPos = (self._currentPage-1)*self:getContentSize().height
        end
        if self._onPageChangeFun~=nil then
            self._onPageChangeFun(self._currentPage,self:getTotalPage())
        end
        if not self._enabledUpdate then
            self._enabledUpdate = true
            self:scheduleUpdate()
        end
    else
        if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
            self._endPos = -self._currentPage*self:getContentSize().width
            self._container:setPositionX(self._endPos)
        elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
            self._endPos = self._currentPage*self:getContentSize().height
            self._container:setPositionY(self._endPos)
        end

        if not self._enabledUpdate then
            self._enabledUpdate = true
            self:scheduleUpdate()
        end
    end
end

function UIPageScrollView:scrollToRender(render,animation)
    if render:getParent()==self then
        local index = render:getLocalZOrder()
        self:scrollToPage( math.floor(index/self._perCount),animation);
    end
end




function UIPageScrollView:_onTouchHandler(event)
    if self.lockDrag then return end

    local type,x,y,prevX,prevY = event.name,event.x,event.y,event.prevX,event.prevY
    if type=="began" then

        self._touchIsDown = true
        self._beganPos.x = x
        self._beganPos.y = y
        self._containerPos.x = self._container:getPositionX()
        self._containerPos.y = self._container:getPositionY()
        self._delta.x = 0
        self._delta.y = 0
        if self._enabledUpdate then
            self:unscheduleUpdate()
            self._enabledUpdate = false
        end
        return true

    elseif type=="moved" then

        self._offsetX = x-self._beganPos.x
        self._offsetY = y-self._beganPos.y

        if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then
            self._endPos = self._containerPos.x + x-self._beganPos.x
        elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then
            self._endPos = self._containerPos.y + y-self._beganPos.y
        end

        self._delta.x = x-prevX
        self._delta.y = y-prevY

        if not self._enabledUpdate then
            self:scheduleUpdate()
            self._enabledUpdate = true
        end

    elseif type=="ended" or type=="cancelled" then

        self._touchIsDown =false 
        self._offsetX = x-self._beganPos.x
        self._offsetY = y-self._beganPos.y

        --判断翻页
        if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL and math.abs(self._offsetX)>1 then
            if math.abs(self._delta.x)>5 or math.abs(self._offsetX)>self:getContentSize().width/2 then
                if self._offsetX>0 then
                    self:prevPage()
                else
                    self:nextPage()
                end
            else
                self:_backPage()
            end
            if not self._enabledUpdate then
                self._enabledUpdate = true
                self:scheduleUpdate()
            end
        elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL and math.abs(self._offsetY)>1 then

            if math.abs(self._delta.y)>5 or math.abs(self._offsetY)>self:getContentSize().height/2 then
                if self._offsetY<0 then
                    self:prevPage()
                else
                    self:nextPage()                  
                end
            else
                self:_backPage()
            end
            if not self._enabledUpdate then
                self._enabledUpdate = true
                self:scheduleUpdate()
            end
        end
    end

end



function UIPageScrollView:_onEnterFrame(dt)
    local currentSpeed = self._touchIsDown==true and self.speed*2 or self.speed

    if self.direction==UIPageScrollView.DIRECTION_HORIZONTAL then

        if  math.abs(self._container:getPositionX() - self._endPos)>1 then
            self._container:setPositionX( self._container:getPositionX()+(self._endPos-self._container:getPositionX())*currentSpeed*0.2)
        else
            self._container:setPositionX( self._endPos )
            if not self._touchIsDown then
                if self._enabledUpdate then
                    self:unscheduleUpdate()
                    self._enabledUpdate = false
                end 
                if self._onScrollOverFun~= nil then
                    self._onScrollOverFun()
                end
            end
        end

    elseif self.direction==UIPageScrollView.DIRECTION_VERTICAL then

        if  math.abs(self._container:getPositionY() - self._endPos)>1 then
            self._container:setPositionY( self._container:getPositionY()+(self._endPos-self._container:getPositionY())*currentSpeed*0.2)
        else
            self._container:setPositionY( self._endPos )
            if not self._touchIsDown then  
                if self._enabledUpdate then
                    self:unscheduleUpdate()
                    self._enabledUpdate = false
                end 
                if self._onScrollOverFun~= nil then
                    self._onScrollOverFun()
                end
            end
        end

    end

    --是否需要render
    for _, child in ipairs(self._container:getChildren()) do
        if  child:getPositionX()+self._container:getPositionX()+self._renderSize.width<0 or
            child:getPositionX()+self._container:getPositionX()-self._renderSize.width>self:getContentSize().width or
            child:getPositionY()+self._container:getPositionY()>self._renderSize.height or
            child:getPositionY()+self._container:getPositionY()+self._renderSize.height<-self:getContentSize().height
        then
            if child:isVisible() then
                child:setVisible(false)
                if child._onBecameInVisibleFun~=nil then
                    child._onBecameInVisibleFun(child)
                end
            end
        else
            if not child:isVisible() then
                child:setVisible(true)
                if child._onBecameVisibleFun~=nil then
                    child._onBecameVisibleFun(child)
                end
            end 
        end
    end
end

function UIPageScrollView:getRenders()
    return self._container:getChildren()
end
--fun回调为参数
function UIPageScrollView:onScrollOver( fun )
    self._onScrollOverFun = fun
    return self
end
--fun的回调参数为 currentPage , totalPage
function UIPageScrollView:onPageChange( fun )
    self._onPageChangeFun = fun 
    return self
end

function UIPageScrollView:dispose()
    self._container = nil 
    self._clipNode = nil
    self._onScrollOverFun = nil
    self._onPageChangeFun  = nil
    UIPageScrollView.super.dispose(self)
end


return UIPageScrollView